#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

const int kMaxN = 2e5 + 10;
const int kMaxT = 2e5 + 10;
const int kInf = 1e9;

struct Graph {
  int n;
  vector<pair<int, int>> g[kMaxN];
  vector<int> cost[kMaxT];
  int dist[kMaxN];

  void AddEdge(int u, int v, int t) {
    g[u].emplace_back(v, t);
  }

  int GetCost(int x, int type) {
    return *lower_bound(cost[type].begin(), cost[type].end(), x);
  }

  void Dijkstra(int s) {
    priority_queue<pair<int, int>> pq;

    fill(dist, dist + n + 1, kInf);
    dist[s] = 1;
    pq.emplace(-dist[s], s);
    while (!pq.empty()) {
      int d = -pq.top().first, u = pq.top().second;

      pq.pop();
      if (dist[u] != d) {
        continue;
      }
      for (const pair<int, int> &e : g[u]) {
        int v = e.first, vd = GetCost(d, e.second) + 1;

        if (dist[v] > vd) {
          dist[v] = vd;
          pq.emplace(-dist[v], v);
        }
      }
    }
  }
} graph;

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  int n, t;

  cin >> n >> t;
  graph.n = n;
  for (int i = 1; i <= t; i++) {
    int m;
    cin >> m;
    for (int j = 0; j < m; j++) {
      int u, v;

      cin >> u >> v;
      graph.AddEdge(u, v, i);
      graph.AddEdge(v, u, i);
    }
  }

  int k;
  cin >> k;
  for (int i = 1; i <= k; i++) {
    int a;

    cin >> a;
    graph.cost[a].emplace_back(i);
  }
  for (int i = 1; i <= t; i++) {
    graph.cost[i].emplace_back(kInf);
  }

  graph.Dijkstra(1);
  if (graph.dist[n] == kInf) {
    cout << "-1\n";
  } else {
    cout << graph.dist[n] - 1 << "\n";
  }

  return 0;
}